package com.jkd.analysis.unpack.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.operator.Contain;
import com.ejlchina.searcher.operator.Equal;
import com.ejlchina.searcher.util.MapUtils;
import com.jkd.analysis.protocol.JinMaCx;
import com.jkd.analysis.protocol.JinMaSz;
import com.jkd.analysis.protocol.JinMaYb;
import com.jkd.analysis.protocol._interface.EquipmentAgreement;
import com.jkd.analysis.unpack.Unpack;
import com.jkd.domain.MeasuringPoint;
import com.jkd.domain.Sensor;
import com.jkd.server.timer.HashedWheelReader;
import com.jkd.taos.domain.SourceData;
import com.jkd.taos.mapper.SourceDatamapper;
import com.jkd.utils.RedisUtil;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * 每个项目的解析方式都可能不同，但是尽量统一。
 */
@Slf4j
@Service
@Scope("prototype")
public class UnpackImpl implements Unpack {

    @Resource
    SourceDatamapper sourceDatamapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private BeanSearcher beanSearcher;

    @Resource
    private HashedWheelReader hashedWheelReader;

    //心跳包为ETUNG开头 如果更换其他厂商的设备需要更换此心跳格式  16进制
    private static final String HEART_PACKAGE = "4554554E47";

    @Value("${tenant.project-id}")
    private String projectId;

    @Value("${tenant.id}")
    private String tenantId;

    /**
     * 解析前的数据全部为16进制字符串
     */
    @Override
    public void toUnpack(ChannelHandlerContext channel, String str) {
        if (heartbeatIs(channel, str)) {//此处应该去判断客户端是哪个DTU 然后去查询该dtu下面的设备指令
            String hex = Convert.hexToStr(str.replaceAll(" ", ""), Charset.forName("UTF-8")).substring(6).trim();
            Map<String, Object> searcher = MapUtils.builder()
                    .field(MeasuringPoint::getDtuCoding, hex).op(Contain.class)
                    .field(MeasuringPoint::getProjectId, projectId).op(Equal.class)
                    .field(MeasuringPoint::getStatus, 0).op(Equal.class)
                    .build();
            List<MeasuringPoint> projectInstructions = beanSearcher.searchAll(MeasuringPoint.class, searcher);
            String instructions = projectInstructions.stream().map(MeasuringPoint::getInstructions).collect(Collectors.joining(","));
            sendCollectionInstructions(channel, instructions);
            return;
        }
        if (str.startsWith(JinMaCx.FRAME_STARTER) &&
                str.replaceAll(" ", "").length() == JinMaCx.MIN_FRAME_LEN) {
            Map<String, Object> searcher = MapUtils.builder()
                    .field(Sensor::getStatus, "0").op(Equal.class)
                    .build();
            List<Sensor> list = beanSearcher.searchAll(Sensor.class, searcher);
            String key = channel.channel().remoteAddress() + "sensorNum";
            String sensorNum = (String) redisUtil.get(key);
            if (ObjectUtils.isEmpty(sensorNum)) {
                return;
            }
            String cexie = list.stream().filter(v -> v.getType().equals("测斜")).map(Sensor::getCoding).collect(Collectors.joining(","));
            if (cexie.contains(sensorNum)) {
                JinMaCx jinMaCx = new JinMaCx();
                List<SourceData> sourceData = jinMaCx.analysis(str, sensorNum);
                saveSourceData(sourceData);
                redisUtil.del(key);
                return;
            }
            String sz = list.stream().filter(v -> v.getType().equals("水准")).map(Sensor::getCoding).collect(Collectors.joining(","));
            if (sz.contains(sensorNum)) {
                JinMaSz jinMaSz = new JinMaSz();
                List<SourceData> sourceData = jinMaSz.analysis(str, sensorNum);
                redisUtil.del(key);
                saveSourceData(sourceData);
                return;
            }
        }
        JinMaYb jinMaYb = new JinMaYb();
        List<SourceData> analysis = jinMaYb.analysis(str, "");
        saveSourceData(analysis);
    }

    //判断心跳
    Boolean heartbeatIs(ChannelHandlerContext channel, String str) {
//        Map<String, Object> searcher = MapUtils.builder()
//                .field(MeasuringPoint::getTenantId, tenantId).op(Equal.class)
//                .field(MeasuringPoint::getStatus, "1").op(Equal.class)
//                .field(MeasuringPoint::getProjectId, projectId).op(Equal.class)
//                .build();
//        List<MeasuringPoint> points = beanSearcher.searchAll(MeasuringPoint.class, searcher);
//
//        if (str.contains("4554554e473a323430333035303034313036353932")) {//5线应变心跳
//            hashedWheelReader.executePer5Min(channel.channel().remoteAddress().toString(), "");
//        } else if (str.contains("4554554e473a323430333035303034313036353735")) {//5线水准倾斜
//            hashedWheelReader.executePer5Min(channel.channel().remoteAddress().toString(), "");
//        } else if (str.contains("4554554e473a323430333035303034313137363230")) {//4线应变
//            hashedWheelReader.executePer5Min(channel.channel().remoteAddress().toString(), "");
//        } else if (str.contains("4554554e473a323430333035303034313137363035")) {//4线水准倾斜
//            hashedWheelReader.executePer5Min(channel.channel().remoteAddress().toString(), "");
//        }
        return str.contains(HEART_PACKAGE) ? true : false;
    }

    public void sendCollectionInstructions(ChannelHandlerContext ctx, String instructions) {
        new Thread(() -> {
            String[] split = instructions.split(",");
            for (String s : split) {
                ctx.writeAndFlush(s);
                redisUtil.set(ctx.channel().remoteAddress().toString() + "sensorNum", getNumber(s));
                System.out.println("发送指令:"+s);
                ThreadUtil.safeSleep(10 * 1000);
            }
        }).start();
    }

    //获取指令中的传感器编号
    public String getNumber(String str) {
        String hex = Convert.hexToStr(str.trim(), Charset.forName("UTF-8"));
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(hex);
        String result = m.replaceAll("").trim();
        return result;
    }

    //异步存储数据
    public int saveSourceData(List<SourceData> sourceDataList) {
        try {
            int res = 0;
            for (SourceData sourceData : sourceDataList) {
                int count = sourceDatamapper.insertOne(sourceData);
                res += count;
            }
            return res;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}
